import%20marimo%0A%0A__generated_with%20%3D%20%220.17.0%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%20Practica%201%3A%20APRENDIZAJE%20PROFUNDO%20Y%20SERIES%20TEMPORALES%0A%20%20%20%20%23%23Fase%201%3A%20An%C3%A1lisis%20y%20Preparaci%C3%B3n%20del%20Dataset%0A%20%20%20%20**Nombres%3A**%20Felipe%20Peralta%20y%20Samantha%20Suquilanda%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20plotly.express%20as%20px%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20from%20scipy.stats%20import%20zscore%0A%0A%20%20%20%20from%20sklearn.preprocessing%20import%20LabelEncoder%2C%20MinMaxScaler%0A%20%20%20%20import%20joblib%0A%20%20%20%20return%20LabelEncoder%2C%20MinMaxScaler%2C%20joblib%2C%20mo%2C%20np%2C%20pd%2C%20px%2C%20zscore%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%201.%20Data%20Engineer%3A%20An%C3%A1lisis%20exploratorio%20de%20datos%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%201.%20Carga%20de%20datos%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(pd)%3A%0A%20%20%20%20df%20%3D%20pd.read_csv('dataset_inventario_secuencial_completo.csv')%0A%20%20%20%20df.tail(10)%0A%20%20%20%20return%20(df%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%23%20Diccionario%20de%20Datos%20(Descripci%C3%B3n%20de%20Variables)%0A%0A%20%20%20%20Basado%20en%20la%20estructura%20del%20dataset%2C%20este%20diccionario%20de%20datos%20describe%20cada%20columna%3A%0A%0A%20%20%20%20%7C%20Variable%20%7C%20Tipo%20de%20Dato%20%7C%20Descripci%C3%B3n%20%7C%0A%20%20%20%20%7C%20%3A---%20%7C%20%3A---%20%7C%20%3A---%20%7C%0A%20%20%20%20%7C%20%60id%60%20%7C%20object%20%7C%20Identificador%20%C3%BAnico%20para%20cada%20registro%20o%20movimiento%20de%20inventario.%20%7C%0A%20%20%20%20%7C%20%60created_at%60%20%7C%20datetime64%5Bns%5D%20%7C%20Fecha%20y%20hora%20en%20que%20se%20cre%C3%B3%20el%20registro%20en%20el%20sistema.%20%7C%0A%20%20%20%20%7C%20%60product_id%60%20%7C%20object%20%7C%20Identificador%20%C3%BAnico%20para%20el%20producto.%20%7C%0A%20%20%20%20%7C%20%60product_name%60%20%7C%20object%20%7C%20Nombre%20descriptivo%20del%20producto.%20%7C%0A%20%20%20%20%7C%20%60product_sku%60%20%7C%20object%20%7C%20(Stock%20Keeping%20Unit)%20C%C3%B3digo%20%C3%BAnico%20interno%20del%20producto.%20%7C%0A%20%20%20%20%7C%20%60supplier_id%60%20%7C%20object%20%7C%20Identificador%20%C3%BAnico%20del%20proveedor%20del%20producto.%20%7C%0A%20%20%20%20%7C%20%60supplier_name%60%20%7C%20object%20%7C%20Nombre%20del%20proveedor.%20%7C%0A%20%20%20%20%7C%20%60quantity_on_hand%60%20%7C%20int64%20%7C%20Cantidad%20f%C3%ADsica%20total%20del%20producto%20actualmente%20en%20el%20almac%C3%A9n.%20%7C%0A%20%20%20%20%7C%20%60quantity_reserved%60%20%7C%20int64%20%7C%20Cantidad%20del%20producto%20que%20est%C3%A1%20apartada%20para%20pedidos%20pendientes.%20%7C%0A%20%20%20%20%7C%20%60quantity_available%60%20%7C%20int64%20%7C%20Cantidad%20real%20disponible%20para%20la%20venta%20(%60on_hand%60%20-%20%60reserved%60).%20%7C%0A%20%20%20%20%7C%20%60minimum_stock_level%60%20%7C%20int64%20%7C%20Nivel%20m%C3%ADnimo%20de%20stock%20antes%20de%20que%20se%20considere%20%22bajo%20stock%22.%20%7C%0A%20%20%20%20%7C%20%60reorder_point%60%20%7C%20int64%20%7C%20Nivel%20de%20stock%20en%20el%20cual%20se%20debe%20generar%20una%20nueva%20orden%20de%20compra.%20%7C%0A%20%20%20%20%7C%20%60optimal_stock_level%60%20%7C%20int64%20%7C%20La%20cantidad%20ideal%20de%20stock%20que%20se%20desea%20mantener.%20%7C%0A%20%20%20%20%7C%20%60reorder_quantity%60%20%7C%20int64%20%7C%20Cantidad%20est%C3%A1ndar%20que%20se%20pide%20en%20una%20nueva%20orden%20de%20compra.%20%7C%0A%20%20%20%20%7C%20%60average_daily_usage%60%20%7C%20float64%20%7C%20Promedio%20de%20unidades%20de%20este%20producto%20usadas%20o%20vendidas%20por%20d%C3%ADa.%20%7C%0A%20%20%20%20%7C%20%60last_order_date%60%20%7C%20datetime64%5Bns%5D%20%7C%20Fecha%20en%20que%20se%20realiz%C3%B3%20la%20%C3%BAltima%20orden%20de%20compra%20de%20este%20producto.%20%7C%0A%20%20%20%20%7C%20%60last_stock_count_date%60%20%7C%20datetime64%5Bns%5D%20%7C%20Fecha%20del%20%C3%BAltimo%20conteo%20f%C3%ADsico%20de%20este%20producto%20en%20el%20almac%C3%A9n.%20%7C%0A%20%20%20%20%7C%20%60unit_cost%60%20%7C%20float64%20%7C%20El%20costo%20de%20adquirir%20una%20sola%20unidad%20del%20producto.%20%7C%0A%20%20%20%20%7C%20%60total_value%60%20%7C%20float64%20%7C%20Valor%20total%20del%20stock%20a%20mano%20(%60quantity_on_hand%60%20*%20%60unit_cost%60).%20%7C%0A%20%20%20%20%7C%20%60expiration_date%60%20%7C%20datetime64%5Bns%5D%20%7C%20Fecha%20de%20caducidad%20del%20lote%20del%20producto%20(si%20aplica).%20%7C%0A%20%20%20%20%7C%20%60batch_number%60%20%7C%20object%20%7C%20N%C3%BAmero%20de%20lote%20para%20trazabilidad.%20%7C%0A%20%20%20%20%7C%20%60warehouse_location%60%20%7C%20object%20%7C%20Ubicaci%C3%B3n%20general%20dentro%20del%20almac%C3%A9n%20(ej.%20%22Bodega%20A%22%2C%20%22Zona%20Fr%C3%ADa%22).%20%7C%0A%20%20%20%20%7C%20%60shelf_location%60%20%7C%20object%20%7C%20Ubicaci%C3%B3n%20espec%C3%ADfica%20en%20la%20estanter%C3%ADa%20(ej.%20%22Pasillo%203%2C%20Rack%20B%22).%20%7C%0A%20%20%20%20%7C%20%60stock_status%60%20%7C%20int64%20%7C%20C%C3%B3digo%20num%C3%A9rico%20que%20representa%20el%20estado%20del%20stock%20(ej.%201%3DEn%20Stock%2C%202%3DBajo%2C%200%3DAgotado).%20%7C%0A%20%20%20%20%7C%20%60is_active%60%20%7C%20bool%20%7C%20Indica%20si%20el%20producto%20es%20un%20%C3%ADtem%20activo%20(%60True%60)%20o%20descontinuado%20(%60False%60).%20%7C%0A%20%20%20%20%7C%20%60last_updated_at%60%20%7C%20datetime64%5Bns%5D%20%7C%20Fecha%20y%20hora%20de%20la%20%C3%BAltima%20modificaci%C3%B3n%20de%20este%20registro.%20%7C%0A%20%20%20%20%7C%20%60notes%60%20%7C%20object%20%7C%20Notas%20adicionales%20o%20comentarios%20sobre%20el%20producto%20o%20lote.%20%7C%0A%20%20%20%20%7C%20%60created_by_id%60%20%7C%20object%20%7C%20Identificador%20del%20usuario%20o%20sistema%20que%20cre%C3%B3%20el%20registro.%20%7C%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%202.%20An%C3%A1lisis%20descriptivo%20inicial%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20print(f%22Dimensiones%3A%20%7Bdf.shape%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20df.info()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%20de%20los%20Resultados%3A**%0A%20%20%20%20-%20Hay%2079173%20entradas%20(filas)%20y%2028%20columnas%20(features).%0A%0A%20%20%20%20-%20Hallazgo%20Cr%C3%ADtico%3A%20existen%2016%20columnas%20de%20tipo%20object.%20Python%20usa%20object%20para%20texto%20(strings).%20Damos%20%C3%A9nfasis%20a%20las%20columnas%20created_at%2C%20last_order_date%2C%20last_stock_count_date%20y%20expiration_date%2C%20que%20est%C3%A1n%20listados%20como%20%22object%22.%0A%0A%20%20%20%20-%20Se%20puede%20observar%20un%20problema%20de%20Tipos%20de%20Datos%20(Dates)%2C%20dado%20que%20vamos%20a%20trabajar%20con%20series%20temporales%2C%20no%20se%20puede%20trabajar%20con%20fechas%20si%20est%C3%A1n%20en%20formato%20de%20texto%20(object).%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%203.%20Limpieza%20de%20datos%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20print(%22Valores%20nulos%3A%20%22)%0A%20%20%20%20df.isnull().sum()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20print(f%22Duplicados%3A%20%7Bdf.duplicated().sum()%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20pd)%3A%0A%20%20%20%20print(%22Correcci%C3%B3n%20de%20tipos%20de%20datos%20a%20datos%20correctos%3A%20%22)%0A%0A%20%20%20%20%23%20Marcar%20productos%20como%20activos%0A%20%20%20%20df%5B%22is_active%22%5D%20%3D%20True%0A%0A%20%20%20%20%23%20Transformar%20datos%20a%20tipo%20fecha%0A%20%20%20%20df.created_at%20%3D%20pd.to_datetime(df.created_at)%0A%20%20%20%20df.last_order_date%20%3D%20pd.to_datetime(df.last_order_date)%0A%20%20%20%20df.last_updated_at%20%3D%20pd.to_datetime(df.last_updated_at)%0A%20%20%20%20df.last_stock_count_date%20%3D%20pd.to_datetime(df.last_stock_count_date)%0A%20%20%20%20df.expiration_date%20%3D%20pd.to_datetime(df.expiration_date)%0A%0A%20%20%20%20df.info()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20primer%20paso%20para%20cualquier%20an%C3%A1lisis%20de%20series%20temporales%20es%20garantizar%20que%20el%20%C3%ADndice%20principal%20del%20conjunto%20de%20datos%20sea%20el%20tiempo.%20Se%20carg%C3%B3%20el%20conjunto%20de%20datos%20original%20y%20se%20determin%C3%B3%20que%20la%20columna%20created_at%20es%20nuestra%20variable%20temporal.%20Utilizando%20pd.to_datetime%2C%20se%20llev%C3%B3%20a%20cabo%20una%20transformaci%C3%B3n%20expl%C3%ADcita%20al%20formato%20de%20fecha%20y%20hora.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%204.%20An%C3%A1lisis%20univariado%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20%23%20Histograma%20interactivo%20del%20costo%20unitario%0A%20%20%20%20fig_costo%20%3D%20px.histogram(%0A%20%20%20%20%20%20%20%20df%2C%0A%20%20%20%20%20%20%20%20x%3D%22unit_cost%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Distribuci%C3%B3n%20del%20Costo%20Unitario%22%2C%0A%20%20%20%20%20%20%20%20marginal%3D%22box%22%0A%20%20%20%20)%0A%0A%20%20%20%20fig_costo.update_traces(%0A%20%20%20%20%20%20%20%20marker_line_color%3D'rgb(8%2C48%2C107)'%2C%0A%20%20%20%20%20%20%20%20marker_line_width%3D1%0A%20%20%20%20)%0A%0A%20%20%20%20fig_costo%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20La%20distribuci%C3%B3n%20de%20los%20valores%20del%20coste%20unitario%20se%20presenta%20en%20el%20histograma.%20Se%20nota%20una%20amplia%20dispersi%C3%B3n%2C%20lo%20cual%20revela%20que%20los%20costos%20oscilan%20de%20manera%20significativa%20entre%20periodos%20o%20productos.%20El%20boxplot%20superior%20verifica%20que%20hay%20valores%20extremos%20(outliers)%2C%20si%20bien%20la%20mayor%20parte%20de%20los%20datos%20se%20agrupan%20en%20el%20rango%20medio.%20Esto%20indica%20una%20considerable%20variabilidad%20que%20podr%C3%ADa%20tener%20un%20impacto%20en%20la%20predicci%C3%B3n%20de%20costos%20a%20trav%C3%A9s%20del%20tiempo.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20%23%20Histograma%20interactivo%20del%20uso%20diario%0A%20%20%20%20fig_uso%20%3D%20px.histogram(%0A%20%20%20%20%20%20%20%20df%2C%0A%20%20%20%20%20%20%20%20x%3D%22average_daily_usage%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Distribuci%C3%B3n%20del%20Uso%20Diario%20Promedio%22%2C%0A%20%20%20%20%20%20%20%20marginal%3D%22box%22%0A%20%20%20%20)%0A%0A%20%20%20%20fig_uso.update_traces(%0A%20%20%20%20%20%20%20%20marker_line_color%3D'rgb(8%2C48%2C107)'%2C%0A%20%20%20%20%20%20%20%20marker_line_width%3D1%0A%20%20%20%20)%0A%0A%20%20%20%20fig_uso%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20La%20variable%20average_daily_usage%20muestra%20una%20distribuci%C3%B3n%20m%C3%A1s%20o%20menos%20uniforme%2C%20lo%20que%20indica%20que%20los%20niveles%20de%20uso%20diario%20no%20se%20agrupan%20en%20una%20tendencia%2C%20sino%20que%20se%20distribuyen%20de%20manera%20equitativa.%20El%20boxplot%20muestra%20una%20amplitud%20significativa%20sin%20valores%20at%C3%ADpicos%20extremos%2C%20lo%20que%20sugiere%20que%20el%20consumo%20o%20uso%20diario%20de%20los%20productos%20es%20estable%20en%20t%C3%A9rminos%20generales.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20df%5B'stock_status'%5D.value_counts()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20%23%20Gr%C3%A1fico%20de%20barras%20interactivo%20para%20'stock_status'%0A%20%20%20%20status_counts%20%3D%20df%5B'stock_status'%5D.value_counts().reset_index()%0A%20%20%20%20status_counts.columns%20%3D%20%5B'Stock%20Status'%2C%20'Count'%5D%0A%0A%20%20%20%20fig_status%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20status_counts%2C%0A%20%20%20%20%20%20%20%20x%3D'Stock%20Status'%2C%0A%20%20%20%20%20%20%20%20y%3D'Count'%2C%0A%20%20%20%20%20%20%20%20title%3D'Frecuencia%20del%20Estado%20del%20Stock'%2C%0A%20%20%20%20%20%20%20%20color%3D'Stock%20Status'%2C%0A%20%20%20%20%20%20%20%20template%3D'plotly_white'%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig_status%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20La%20variable%20stock_status%20muestra%20una%20fuerte%20desproporci%C3%B3n%3A%20la%20categor%C3%ADa%20%E2%80%9C3%E2%80%9D%20domina%20con%20m%C3%A1s%20de%2077%20000%20registros%2C%20mientras%20que%20los%20otros%20estados%20son%20minoritarios%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20top_10_suppliers%20%3D%20df%5B'supplier_name'%5D.value_counts().nlargest(10).reset_index()%0A%20%20%20%20top_10_suppliers.columns%20%3D%20%5B'Proveedor'%2C%20'Registros'%5D%0A%0A%20%20%20%20print(top_10_suppliers)%0A%0A%20%20%20%20fig_suppliers%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20top_10_suppliers%2C%0A%20%20%20%20%20%20%20%20x%3D'Proveedor'%2C%0A%20%20%20%20%20%20%20%20y%3D'Registros'%2C%0A%20%20%20%20%20%20%20%20title%3D'Top%2010%20Proveedores%20por%20Nro.%20de%20Registros%20de%20Producto'%2C%0A%20%20%20%20%20%20%20%20template%3D'plotly_white'%0A%20%20%20%20)%0A%0A%20%20%20%20fig_suppliers.update_traces(%0A%20%20%20%20%20%20%20%20marker_line_color%3D'rgb(0%2C0%2C0)'%2C%20%0A%20%20%20%20%20%20%20%20marker_line_width%3D1.5%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20)%0A%0A%20%20%20%20fig_suppliers%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20gr%C3%A1fico%20muestra%20los%20diez%20proveedores%20con%20mayor%20n%C3%BAmero%20de%20registros%20en%20el%20dataset.%20Se%20observa%20una%20distribuci%C3%B3n%20bastante%20homog%C3%A9nea%2C%20destacando%20Banca%20Privada%20JWW%20S.L.%20y%20Hnos%20Raya%20S.L.%20como%20los%20principales.%20Esto%20sugiere%20una%20concentraci%C3%B3n%20moderada%20en%20pocos%20proveedores%2C%20lo%20cual%20puede%20influir%20en%20la%20disponibilidad%20y%20frecuencia%20de%20productos%20dentro%20de%20las%20series%20temporales.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%205.%20An%C3%A1lisis%20Bivariado%20y%20Multivariado%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20%23%20Scatter%20plot%3A%20Costo%20Unitario%20vs.%20Cantidad%20Disponible%0A%20%20%20%20fig_scatter%20%3D%20px.scatter(%0A%20%20%20%20%20%20%20%20df%2C%0A%20%20%20%20%20%20%20%20x%3D%22unit_cost%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22quantity_available%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Relaci%C3%B3n%20entre%20Costo%20Unitario%20y%20Cantidad%20Disponible%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20hover_data%3D%5B%22product_name%22%5D%0A%20%20%20%20)%0A%0A%20%20%20%20fig_scatter.update_traces(%0A%20%20%20%20%20%20%20%20marker%3Ddict(line%3Ddict(width%3D1%2C%20color%3D'DarkSlateGrey'))%0A%20%20%20%20)%0A%0A%20%20%20%20fig_scatter%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20La%20relaci%C3%B3n%20entre%20el%20costo%20unitario%20y%20la%20cantidad%20disponible%20no%20es%20lineal%2C%20como%20lo%20demuestra%20el%20diagrama%20de%20dispersi%C3%B3n.%20El%20precio%20no%20determina%20directamente%20el%20nivel%20del%20stock%2C%20dado%20que%20los%20puntos%20se%20distribuyen%20al%20azar.%20Esto%20subraya%20la%20importancia%20de%20incorporar%20variables%20temporales%20o%20categ%C3%B3ricas%20adicionales%20para%20representar%20la%20demanda%20de%20manera%20precisa.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20numeric_cols%20%3D%20df.select_dtypes(include%3D%5B'int64'%2C%20'float64'%5D)%0A%0A%20%20%20%20corr_matrix%20%3D%20numeric_cols.corr()%0A%0A%20%20%20%20%23%20Visualizar%20el%20heatmap%0A%20%20%20%20fig_heatmap%20%3D%20px.imshow(%0A%20%20%20%20%20%20%20%20corr_matrix%2C%0A%20%20%20%20%20%20%20%20text_auto%3DTrue%2C%0A%20%20%20%20%20%20%20%20aspect%3D%22auto%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Mapa%20de%20Calor%20de%20Correlaci%C3%B3n%20Num%C3%A9rica%22%2C%0A%20%20%20%20%20%20%20%20color_continuous_scale%3D'RdBu_r'%2C%20%0A%20%20%20%20%20%20%20%20zmin%3D-1%2C%0A%20%20%20%20%20%20%20%20zmax%3D1%0A%20%20%20%20)%0A%0A%20%20%20%20fig_heatmap%0A%20%20%20%20return%20(numeric_cols%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20mapa%20de%20correlaci%C3%B3n%20muestra%20relaciones%20fuertes%20entre%20ciertas%20variables%2C%20como%20quantity_on_hand%20y%20quantity_available%20(r%20%E2%89%88%200.99)%2C%20o%20entre%20reorder_point%20y%20minimum_stock_level%20(r%20%E2%89%88%200.90).%20Estas%20correlaciones%20indican%20redundancia%20informativa%20entre%20variables%20relacionadas%20con%20el%20inventario.%20En%20contraste%2C%20unit_cost%20y%20average_daily_usage%20presentan%20baja%20correlaci%C3%B3n%20con%20las%20dem%C3%A1s%2C%20sugiriendo%20independencia%20y%20potencial%20valor%20predictivo.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20%23%20Boxplot%3A%20Cantidad%20Disponible%20vs.%20Estado%20del%20Stock%0A%20%20%20%20fig_box%20%3D%20px.box(%0A%20%20%20%20%20%20%20%20df%2C%0A%20%20%20%20%20%20%20%20x%3D%22stock_status%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22quantity_available%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22stock_status%22%2C%20%0A%20%20%20%20%20%20%20%20title%3D%22Distribuci%C3%B3n%20de%20Cantidad%20Disponible%20por%20Estado%20del%20Stock%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%0A%20%20%20%20)%0A%0A%20%20%20%20fig_box%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20boxplot%20muestra%20que%20el%20estado%20del%20stock%203%20concentra%20la%20mayor%20cantidad%20de%20productos%20disponibles%2C%20con%20un%20rango%20amplio%20de%20valores.%20Los%20dem%C3%A1s%20estados%20presentan%20cantidades%20muy%20reducidas.%20Esto%20refuerza%20la%20desproporci%C3%B3n%20en%20la%20variable%20stock_status%20detectada%20previamente%20y%20puede%20requerir%20normalizaci%C3%B3n%20o%20reagrupaci%C3%B3n%20antes%20del%20modelado.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20pd%2C%20px)%3A%0A%20%20%20%20cross_tab%20%3D%20pd.crosstab(df%5B'warehouse_location'%5D%2C%20df%5B'stock_status'%5D)%0A%20%20%20%20cross_tab_tidy%20%3D%20cross_tab.reset_index().melt(id_vars%3D'warehouse_location')%0A%20%20%20%20cross_tab_tidy.head()%0A%0A%20%20%20%20%23%20Crear%20el%20gr%C3%A1fico%20de%20barras%20agrupado%0A%20%20%20%20fig_grouped_bar%20%3D%20px.bar(%0A%20%20%20%20%20%20%20%20cross_tab_tidy%2C%0A%20%20%20%20%20%20%20%20x%3D%22warehouse_location%22%2C%0A%20%20%20%20%20%20%20%20y%3D%22value%22%2C%0A%20%20%20%20%20%20%20%20color%3D%22stock_status%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Estado%20del%20Stock%20por%20Ubicaci%C3%B3n%20del%20Almac%C3%A9n%22%2C%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20barmode%3D%22group%22%0A%20%20%20%20)%0A%0A%20%20%20%20fig_grouped_bar%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20La%20distribuci%C3%B3n%20del%20stock%20por%20ubicaci%C3%B3n%20evidencia%20una%20homogeneidad%20entre%20los%20almacenes%2C%20con%20el%20estado%20%223%22%20predominando%20en%20todos%20los%20casos.%20Esto%20indica%20que%20la%20administraci%C3%B3n%20de%20inventarios%20es%20parecida%20entre%20los%20centros%20y%20no%20hay%20diferencias%20operacionales%20importantes%20en%20funci%C3%B3n%20de%20la%20ubicaci%C3%B3n%2C%20a%20pesar%20de%20que%20el%20desbalance%20general%20en%20el%20estado%20del%20stock%20persiste.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20px)%3A%0A%20%20%20%20pairplot_cols%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'quantity_available'%2C%0A%20%20%20%20%20%20%20%20'unit_cost'%2C%0A%20%20%20%20%20%20%20%20'average_daily_usage'%2C%0A%20%20%20%20%20%20%20%20'reorder_point'%2C%0A%20%20%20%20%20%20%20%20'total_value'%2C%0A%20%20%20%20%20%20%20%20'stock_status'%0A%20%20%20%20%5D%0A%0A%20%20%20%20fig_pairplot%20%3D%20px.scatter_matrix(%0A%20%20%20%20%20%20%20%20df%5Bpairplot_cols%5D%2C%0A%20%20%20%20%20%20%20%20dimensions%3D%5B'quantity_available'%2C%20'unit_cost'%2C%20'average_daily_usage'%2C%20'reorder_point'%5D%2C%0A%20%20%20%20%20%20%20%20color%3D%22stock_status%22%2C%20%20%23%20Colorea%20los%20puntos%20por%20estado%20de%20stock%0A%20%20%20%20%20%20%20%20title%3D%22Pairplot%20de%20Variables%20Clave%20(Coloreado%20por%20Estado%20de%20Stock)%22%0A%20%20%20%20)%0A%0A%20%20%20%20fig_pairplot.update_traces(%0A%20%20%20%20%20%20%20%20marker%3Ddict(size%3D3%2C%20line%3Ddict(width%3D0.5%2C%20color%3D'DarkSlateGrey'))%0A%20%20%20%20)%0A%0A%20%20%20%20fig_pairplot%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20pairplot%20permite%20observar%20relaciones%20bivariadas%20entre%20variables%20num%C3%A9ricas%20clave.%20Se%20confirma%20una%20fuerte%20relaci%C3%B3n%20entre%20quantity_on_hand%20y%20quantity_available%2C%20mientras%20que%20unit_cost%20y%20average_daily_usage%20no%20muestran%20patrones%20evidentes.%20Los%20colores%20del%20estado%20de%20stock%20revelan%20que%20la%20mayor%C3%ADa%20de%20registros%20pertenecen%20a%20la%20clase%203%2C%20indicando%20un%20sesgo%20que%20deber%C3%A1%20controlarse%20en%20las%20fases%20de%20modelado.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%206.%20Detecci%C3%B3n%20de%20outliers%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20numeric_cols)%3A%0A%20%20%20%20%23%20Iterar%20sobre%20cada%20columna%20para%20calcular%20outliers%0A%20%20%20%20for%20col%20in%20numeric_cols%3A%0A%20%20%20%20%20%20%20%20Q1%20%3D%20df%5Bcol%5D.quantile(0.25)%0A%20%20%20%20%20%20%20%20Q3%20%3D%20df%5Bcol%5D.quantile(0.75)%0A%20%20%20%20%20%20%20%20IQR%20%3D%20Q3%20-%20Q1%0A%0A%20%20%20%20%20%20%20%20lower_bound%20%3D%20Q1%20-%201.5%20*%20IQR%0A%20%20%20%20%20%20%20%20upper_bound%20%3D%20Q3%20%2B%201.5%20*%20IQR%0A%0A%20%20%20%20%20%20%20%20outliers%20%3D%20df%5B(df%5Bcol%5D%20%3C%20lower_bound)%20%7C%20(df%5Bcol%5D%20%3E%20upper_bound)%5D%0A%0A%20%20%20%20%20%20%20%20if%20not%20outliers.empty%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%5CnColumna%3A%20'%7Bcol%7D'%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22L%C3%ADmites%20(IQR)%3A%20(%7Blower_bound%3A.2f%7D%2C%20%7Bupper_bound%3A.2f%7D)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Total%20de%20outliers%20detectados%3A%20%7Blen(outliers)%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20print(outliers%5B%5Bcol%2C%20'product_name'%5D%5D.sort_values(by%3Dcol%2C%20ascending%3DFalse).head())%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%5CnColumna%3A%20'%7Bcol%7D'%20-%3E%20Sin%20outliers%20(seg%C3%BAn%20IQR).%22)%0A%20%20%20%20return%20(outliers%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20an%C3%A1lisis%20mediante%20el%20rango%20intercuart%C3%ADlico%20(IQR)%20muestra%20ausencia%20de%20outliers%20en%20la%20mayor%C3%ADa%20de%20variables%20num%C3%A9ricas%2C%20excepto%20en%20total_value%20(899%20valores%20extremos)%20y%20stock_status%20(2058%20registros%20fuera%20del%20rango%20esperado).%20Esto%20indica%20que%2C%20aunque%20el%20dataset%20es%20consistente%2C%20existen%20valores%20an%C3%B3malos%20en%20variables%20relacionadas%20con%20el%20valor%20total%20y%20estado%20del%20stock%2C%20que%20podr%C3%ADan%20afectar%20la%20estabilidad%20del%20modelo%20si%20no%20se%20tratan%20adecuadamente.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df%2C%20np%2C%20numeric_cols%2C%20outliers%2C%20zscore)%3A%0A%20%20%20%20threshold%20%3D%203%20%0A%0A%20%20%20%20for%20col_2%20in%20numeric_cols%3A%0A%20%20%20%20%20%20%20%20z_scores%20%3D%20np.abs(zscore(df%5Bcol_2%5D))%0A%0A%20%20%20%20%20%20%20%20outliers_2%20%3D%20df%5Bz_scores%20%3E%20threshold%5D%0A%0A%20%20%20%20%20%20%20%20if%20not%20outliers.empty%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%5CnColumna%3A%20'%7Bcol_2%7D'%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Umbral%20(Z-score)%3A%20%7Bthreshold%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Total%20de%20outliers%20detectados%3A%20%7Blen(outliers_2)%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20print(outliers%5B%5Bcol_2%2C%20'product_name'%5D%5D.sort_values(by%3Dcol_2%2C%20ascending%3DFalse).head())%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%5CnColumna%3A%20'%7Bcol_2%7D'%20-%3E%20Sin%20outliers%20(Z-score%20%3C%20%7Bthreshold%7D).%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20m%C3%A9todo%20del%20Z-score%20confirm%C3%B3%20la%20ausencia%20de%20valores%20at%C3%ADpicos%20en%20la%20mayor%C3%ADa%20de%20las%20variables%20num%C3%A9ricas.%20Solo%20se%20detectaron%20outliers%20en%20total_value%20(341%20casos)%20y%20en%20stock_status%20(2058%20registros)%2C%20coincidiendo%20con%20los%20resultados%20obtenidos%20por%20el%20m%C3%A9todo%20IQR.%20Esto%20refuerza%20la%20consistencia%20general%20del%20dataset%2C%20pero%20tambi%C3%A9n%20evidencia%20la%20necesidad%20de%20revisar%20estas%20dos%20variables%20para%20evitar%20sesgos%20en%20el%20entrenamiento%20del%20modelo.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%202.%20Feature%20Engineering%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df)%3A%0A%20%20%20%20print(%22Iniciando%20Feature%20Engineering...%22)%0A%0A%20%20%20%20df_feat%20%3D%20df.copy()%0A%0A%20%20%20%20%23%20Usando%20'created_at'%20como%20la%20fecha%20principal%20del%20registro%0A%20%20%20%20base_date%20%3D%20df_feat%5B'created_at'%5D%0A%0A%20%20%20%20df_feat%5B'dia_del_mes'%5D%20%3D%20base_date.dt.day%0A%20%20%20%20df_feat%5B'dia_de_la_semana'%5D%20%3D%20base_date.dt.dayofweek%20%23%20Lunes%3D0%2C%20Domingo%3D6%0A%20%20%20%20df_feat%5B'mes'%5D%20%3D%20base_date.dt.month%0A%20%20%20%20df_feat%5B'trimestre'%5D%20%3D%20base_date.dt.quarter%0A%20%20%20%20df_feat%5B'es_fin_de_semana'%5D%20%3D%20df_feat%5B'dia_de_la_semana'%5D.isin(%5B5%2C%206%5D).astype(int)%0A%0A%20%20%20%20print(%22Variables%20temporales%20creadas.%22)%0A%0A%20%20%20%20%23%201.%20D%C3%ADas%20restantes%20hasta%20vencimiento%0A%20%20%20%20df_feat%5B'dias_para_vencimiento'%5D%20%3D%20(df_feat%5B'expiration_date'%5D%20-%20base_date).dt.days%0A%20%20%20%20%23%20Manejar%20valores%20negativos%20(si%20'created_at'%20es%20posterior%20a%20'expiration_date')%0A%20%20%20%20df_feat%5B'dias_para_vencimiento'%5D%20%3D%20df_feat%5B'dias_para_vencimiento'%5D.fillna(0)%0A%20%20%20%20df_feat%5B'dias_para_vencimiento'%5D%20%3D%20df_feat%5B'dias_para_vencimiento'%5D.apply(lambda%20x%3A%20max(0%2C%20x))%0A%0A%20%20%20%20%23%202.%20Antig%C3%BCedad%20del%20producto%20(Sugerido%20en%20la%20gu%C3%ADa)%0A%20%20%20%20df_feat%5B'antiguedad_producto_dias'%5D%20%3D%20(base_date%20-%20df_feat%5B'last_stock_count_date'%5D).dt.days%0A%20%20%20%20df_feat%5B'antiguedad_producto_dias'%5D%20%3D%20df_feat%5B'antiguedad_producto_dias'%5D.fillna(0)%0A%20%20%20%20df_feat%5B'antiguedad_producto_dias'%5D%20%3D%20df_feat%5B'antiguedad_producto_dias'%5D.apply(lambda%20x%3A%20max(0%2C%20x))%0A%0A%0A%20%20%20%20%23%203.%20Ratio%20de%20uso%20sobre%20stock%20(Sugerido%20en%20la%20gu%C3%ADa)%0A%20%20%20%20df_feat%5B'ratio_uso_stock'%5D%20%3D%20df_feat%5B'average_daily_usage'%5D%20%2F%20(df_feat%5B'quantity_available'%5D%20%2B%201)%0A%0A%20%20%20%20%23%20Mostramos%20las%20columnas%20clave%20y%20las%20nuevas%20que%20creamos%0A%20%20%20%20columnas_a_mostrar%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'created_at'%2C%20%0A%20%20%20%20%20%20%20%20'product_id'%2C%20%0A%20%20%20%20%20%20%20%20'quantity_available'%2C%20%0A%20%20%20%20%20%20%20%20'average_daily_usage'%2C%0A%20%20%20%20%20%20%20%20'expiration_date'%2C%0A%20%20%20%20%20%20%20%20%23%20---%20Nuevas%20---%0A%20%20%20%20%20%20%20%20'dia_de_la_semana'%2C%20%0A%20%20%20%20%20%20%20%20'mes'%2C%20%0A%20%20%20%20%20%20%20%20'es_fin_de_semana'%2C%0A%20%20%20%20%20%20%20%20'dias_para_vencimiento'%2C%0A%20%20%20%20%20%20%20%20'antiguedad_producto_dias'%2C%0A%20%20%20%20%20%20%20%20'ratio_uso_stock'%0A%20%20%20%20%5D%0A%0A%20%20%20%20print(df_feat%5Bcolumnas_a_mostrar%5D.head())%0A%20%20%20%20print(df_feat%5Bcolumnas_a_mostrar%5D.info())%0A%20%20%20%20return%20(df_feat%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20En%20esta%20etapa%20se%20generaron%20variables%20temporales%20clave%20como%20%22dia_de_la_semana%22%2C%20%22mes%22%2C%20%22es_fin_de_semana%22%2C%20%22dias_para_vencimiento%22%20y%20%22antiguedad_producto_dias%22%2C%20junto%20con%20el%20indicador%20ratio_uso_stock.%0A%20%20%20%20Estas%20nuevas%20columnas%20permitir%C3%A1n%20que%20el%20modelo%20capture%20patrones%20estacionales%20y%20c%C3%ADclicos%20de%20demanda%2C%20fundamentales%20para%20las%20series%20temporales.%20Adem%C3%A1s%2C%20todas%20las%20variables%20fueron%20correctamente%20tipadas%20y%20sin%20valores%20nulos%2C%20garantizando%20calidad%20en%20los%20datos%20de%20entrada.%0A%20%20%20%20-%20El%20nuevo%20DataFrame%20tiene%2079.174%20entradas%20y%2011%20columnas%2C%20sin%20valores%20ausentes.%20Las%20variables%20poseen%20tipos%20apropiados%20(int32%2C%20int64%2C%20float64%2C%20datetime64)%2C%20lo%20que%20indica%20una%20conversi%C3%B3n%20adecuada%20de%20valores%20num%C3%A9ricos%20y%20fechas.%0A%20%20%20%20Este%20control%20garantiza%20que%20los%20datos%20est%C3%A9n%20preparados%20para%20ser%20codificados%2C%20escalados%20y%20utilizados%20en%20la%20creaci%C3%B3n%20de%20secuencias%20temporales.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%203.%20Codificaci%C3%B3n%20y%20Escalado%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LabelEncoder%2C%20df_feat%2C%20joblib%2C%20pd)%3A%0A%20%20%20%20df_proc%20%3D%20df_feat.copy()%0A%0A%20%20%20%20%23%20Codificador%20para%20product_id%0A%20%20%20%20le_product_id%20%3D%20LabelEncoder()%0A%20%20%20%20df_proc%5B'product_id_encoded'%5D%20%3D%20le_product_id.fit_transform(df_proc%5B'product_id'%5D)%0A%20%20%20%20joblib.dump(le_product_id%2C%20'le_product_id.joblib')%20%23%20Guardar%0A%0A%20%20%20%20%23%20Codificador%20para%20supplier_id%0A%20%20%20%20le_supplier_id%20%3D%20LabelEncoder()%0A%20%20%20%20df_proc%5B'supplier_id_encoded'%5D%20%3D%20le_supplier_id.fit_transform(df_proc%5B'supplier_id'%5D)%0A%20%20%20%20joblib.dump(le_supplier_id%2C%20'le_supplier_id.joblib')%20%23%20Guardar%0A%0A%20%20%20%20categorias_onehot%20%3D%20%5B'warehouse_location'%2C%20'stock_status'%5D%0A%20%20%20%20df_proc%20%3D%20pd.get_dummies(df_proc%2C%20columns%3Dcategorias_onehot%2C%20drop_first%3DTrue)%0A%0A%20%20%20%20print(%22%5CnColumnas%20despu%C3%A9s%20de%20One-Hot%20Encoding%3A%22)%0A%20%20%20%20print(%5Bcol%20for%20col%20in%20df_proc.columns%20if%20'warehouse_location_'%20in%20col%20or%20'stock_status_'%20in%20col%5D)%0A%20%20%20%20return%20(df_proc%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%20Se%20aplic%C3%B3%20Label%20Encoding%20a%20los%20identificadores%20(product_id%2C%20supplier_id)%20para%20convertirlos%20en%20valores%20num%C3%A9ricos%20%C3%BAnicos%2C%20y%20One-Hot%20Encoding%20para%20las%20variables%20categ%C3%B3ricas%20(warehouse_location%2C%20stock_status).%0A%20%20%20%20Esta%20combinaci%C3%B3n%20preserva%20la%20informaci%C3%B3n%20nominal%20sin%20introducir%20jerarqu%C3%ADas%20falsas%2C%20lo%20que%20resulta%20esencial%20para%20modelos%20neuronales%20que%20procesan%20datos%20categ%C3%B3ricos%20junto%20con%20variables%20continuas.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MinMaxScaler%2C%20df_proc%2C%20joblib)%3A%0A%20%20%20%20columnas_numericas%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'quantity_on_hand'%2C%20'quantity_reserved'%2C%20'quantity_available'%2C%0A%20%20%20%20%20%20%20%20'minimum_stock_level'%2C%20'reorder_point'%2C%20'optimal_stock_level'%2C%0A%20%20%20%20%20%20%20%20'reorder_quantity'%2C%20'average_daily_usage'%2C%20'unit_cost'%2C%20'total_value'%2C%0A%20%20%20%20%20%20%20%20'dia_del_mes'%2C%20'dia_de_la_semana'%2C%20'mes'%2C%20'trimestre'%2C%20'es_fin_de_semana'%2C%0A%20%20%20%20%20%20%20%20'dias_para_vencimiento'%2C%20'antiguedad_producto_dias'%2C%20'ratio_uso_stock'%0A%20%20%20%20%5D%0A%0A%20%20%20%20scaler%20%3D%20MinMaxScaler()%0A%20%20%20%20df_proc%5Bcolumnas_numericas%5D%20%3D%20scaler.fit_transform(df_proc%5Bcolumnas_numericas%5D)%0A%20%20%20%20joblib.dump(scaler%2C%20'min_max_scaler.joblib')%0A%0A%20%20%20%20print(%22%5CnEscalar%20Variables%20Num%C3%A9ricas%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20Mediante%20el%20MinMaxScaler%2C%20todas%20las%20variables%20num%C3%A9ricas%20fueron%20normalizadas%20al%20rango%20%5B0%2C1%5D.%20Esto%20facilita%20la%20convergencia%20del%20modelo%20y%20evita%20que%20las%20variables%20con%20magnitudes%20grandes%20dominen%20el%20aprendizaje.%0A%20%20%20%20-%20El%20escalador%20se%20guard%C3%B3%20con%20joblib%2C%20asegurando%20su%20reutilizaci%C3%B3n%20durante%20la%20fase%20de%20predicci%C3%B3n%20para%20mantener%20la%20coherencia%20entre%20entrenamiento%20y%20despliegue.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_proc)%3A%0A%20%20%20%20print(%22%5CnDataFrame%20Procesado%22)%0A%20%20%20%20print(df_proc.head())%0A%0A%20%20%20%20columnas_modelo%20%3D%20df_proc.select_dtypes(exclude%3D%5B'object'%2C%20'datetime64%5Bns%5D'%5D).columns%0A%20%20%20%20print(df_proc%5Bcolumnas_modelo%5D.info())%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20El%20DataFrame%20final%20integra%20las%20variables%20originales%20y%20las%20transformadas%2C%20alcanzando%2045%20columnas.%20Se%20observan%20variables%20num%C3%A9ricas%20escaladas%2C%20categ%C3%B3ricas%20codificadas%20y%20booleanas%20derivadas%20del%20One-Hot%20Encoding.%0A%0A%20%20%20%20-%20El%20resultado%20es%20un%20dataset%20completamente%20limpio%2C%20estructurado%20y%20listo%20para%20modelado%20secuencial%2C%20cumpliendo%20con%20los%20criterios%20de%20la%20Fase%201%20de%20la%20gu%C3%ADa%20de%20pr%C3%A1ctica%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%23%204.%20Preparaci%C3%B3n%20de%20Secuencias%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_feat%2C%20df_proc)%3A%0A%20%20%20%20df_proc%5B'created_at'%5D%20%3D%20df_feat%5B'created_at'%5D%0A%20%20%20%20print(%22DataFrame%20'df_proc'%20listo%20para%20la%20creaci%C3%B3n%20de%20secuencias.%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22**An%C3%A1lisis%3A**%20El%20DataFrame%20%22df_proc%22%20est%C3%A1%20totalmente%20listo%20para%20generar%20secuencias%20temporales.%20Se%20asegura%20el%20orden%20cronol%C3%B3gico%20apropiado%20para%20crear%20ventanas%20de%20tiempo%20que%20nutran%20el%20modelo%20RNN%20si%20se%20conserva%20la%20columna%20created_at%20en%20formato%20de%20fecha.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_proc)%3A%0A%20%20%20%20%23%207%20d%C3%ADas.%0A%20%20%20%20N_STEPS%20%3D%207%20%0A%0A%20%20%20%20%23%20Columna%20objetivo%0A%20%20%20%20TARGET_COLUMN%20%3D%20'quantity_available'%0A%0A%20%20%20%20FEATURE_COLUMNS%20%3D%20%5B%0A%20%20%20%20%20%20%20%20'quantity_on_hand'%2C%20'quantity_reserved'%2C%20'quantity_available'%2C%0A%20%20%20%20%20%20%20%20'minimum_stock_level'%2C%20'reorder_point'%2C%20'optimal_stock_level'%2C%0A%20%20%20%20%20%20%20%20'reorder_quantity'%2C%20'average_daily_usage'%2C%20'unit_cost'%2C%20'total_value'%2C%0A%20%20%20%20%20%20%20%20'is_active'%2C%20'dia_del_mes'%2C%20'dia_de_la_semana'%2C%20'mes'%2C%20'trimestre'%2C%0A%20%20%20%20%20%20%20%20'es_fin_de_semana'%2C%20'dias_para_vencimiento'%2C%20'antiguedad_producto_dias'%2C%0A%20%20%20%20%20%20%20%20'ratio_uso_stock'%2C%20'product_id_encoded'%2C%20'supplier_id_encoded'%2C%0A%20%20%20%20%20%20%20%20'warehouse_location_Almac%C3%A9n%20Este'%2C%20'warehouse_location_Almac%C3%A9n%20Norte'%2C%0A%20%20%20%20%20%20%20%20'warehouse_location_Almac%C3%A9n%20Oeste'%2C%20'warehouse_location_Almac%C3%A9n%20Sur'%2C%0A%20%20%20%20%20%20%20%20'warehouse_location_Centro%20Distribuci%C3%B3n%201'%2C%0A%20%20%20%20%20%20%20%20'warehouse_location_Centro%20Distribuci%C3%B3n%202'%2C%20'stock_status_1'%2C%0A%20%20%20%20%20%20%20%20'stock_status_2'%2C%20'stock_status_3'%0A%20%20%20%20%5D%0A%0A%20%20%20%20missing_cols%20%3D%20%5Bcol%20for%20col%20in%20FEATURE_COLUMNS%20if%20col%20not%20in%20df_proc.columns%5D%0A%20%20%20%20if%20missing_cols%3A%0A%20%20%20%20%20%20%20%20print(f%22Faltan%20las%20columnas%3A%20%7Bmissing_cols%7D%22)%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print(f%22Todas%20las%20%7Blen(FEATURE_COLUMNS)%7D%20features%20est%C3%A1n%20presentes.%22)%0A%0A%20%20%20%20if%20TARGET_COLUMN%20not%20in%20FEATURE_COLUMNS%3A%0A%20%20%20%20%20%20%20%20print(f%22Target%20'%7BTARGET_COLUMN%7D'%20no%20en%20features.%22)%0A%20%20%20%20return%20FEATURE_COLUMNS%2C%20N_STEPS%2C%20TARGET_COLUMN%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20La%20variable%20objetivo%20quantity_available%20se%20define%20y%20se%20fijan%20siete%20pasos%20temporales%20(N_STEPS%20%3D%207)%2C%20que%20corresponden%20a%20una%20semana%20de%20observaciones.%0A%20%20%20%20-%20Las%2030%20caracter%C3%ADsticas%20elegidas%20contienen%20variables%20num%C3%A9ricas%2C%20categ%C3%B3ricas%20codificadas%20y%20temporales%20derivadas%2C%20lo%20cual%20posibilita%20la%20identificaci%C3%B3n%20de%20patrones%20conductuales%20en%20el%20inventario%20a%20trav%C3%A9s%20del%20tiempo.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_proc)%3A%0A%20%20%20%20print(%22%5CnDividiendo%20en%20Train%20y%20Validation%22)%0A%0A%20%20%20%20df_sorted%20%3D%20df_proc.sort_values(by%3D'created_at')%0A%0A%20%20%20%20split_percentage%20%3D%200.8%0A%20%20%20%20split_index%20%3D%20int(len(df_sorted)%20*%20split_percentage)%0A%0A%20%20%20%20train_df%20%3D%20df_sorted.iloc%5B%3Asplit_index%5D%0A%20%20%20%20val_df%20%3D%20df_sorted.iloc%5Bsplit_index%3A%5D%0A%0A%20%20%20%20print(f%22Total%20de%20registros%3A%20%7Blen(df_sorted)%7D%22)%0A%20%20%20%20print(f%22Set%20de%20Entrenamiento%20(Train)%3A%20%7Blen(train_df)%7D%20registros%22)%0A%20%20%20%20print(f%22Set%20de%20Validaci%C3%B3n%20(Val)%3A%20%7Blen(val_df)%7D%20registros%22)%0A%20%20%20%20print(f%22Corte%20temporal%20en%3A%20%7Bval_df%5B'created_at'%5D.min()%7D%22)%0A%20%20%20%20return%20train_df%2C%20val_df%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20El%20dataset%20se%20ordena%20cronol%C3%B3gicamente%20por%20created_at%20y%20se%20divide%20en%2080%20%25%20para%20entrenamiento%20y%2020%20%25%20para%20validaci%C3%B3n.%0A%20%20%20%20-%20El%20corte%20temporal%20garantiza%20que%20los%20datos%20futuros%20no%20influyan%20en%20el%20entrenamiento%2C%20manteniendo%20la%20coherencia%20temporal%20fundamental%20en%20series%20temporales.%0A%20%20%20%20-%20El%20resultado%20muestra%2079%20174%20registros%20totales%3A%2063%20339%20para%20Train%20y%2015%20835%20para%20Validation.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20create_sequences(data_df%2C%20product_group%2C%20n_steps%2C%20feature_cols%2C%20target_col)%3A%0A%20%20%20%20%20%20%20%20product_data%20%3D%20data_df%5Bdata_df%5B'product_id_encoded'%5D%20%3D%3D%20product_group%5D.copy()%0A%0A%20%20%20%20%20%20%20%20product_data%20%3D%20product_data.sort_values(by%3D'created_at')%0A%0A%20%20%20%20%20%20%20%20features%20%3D%20product_data%5Bfeature_cols%5D.values%0A%20%20%20%20%20%20%20%20target%20%3D%20product_data%5Btarget_col%5D.values%0A%0A%20%20%20%20%20%20%20%20X%2C%20y%20%3D%20%5B%5D%2C%20%5B%5D%0A%0A%20%20%20%20%20%20%20%20for%20i%20in%20range(n_steps%2C%20len(product_data))%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20X.append(features%5Bi-n_steps%3Ai%5D)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20y.append(target%5Bi%5D)%0A%0A%20%20%20%20%20%20%20%20if%20len(X)%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20np.array(X)%2C%20np.array(y)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20None%2C%20None%0A%20%20%20%20return%20(create_sequences%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20Esta%20funci%C3%B3n%20genera%20secuencias%20deslizantes%20de%20N_STEPS%20observaciones%20previas%20para%20cada%20producto.%0A%20%20%20%20-%20Cada%20ventana%20temporal%20contiene%20los%20valores%20de%20las%20features%20definidas%20y%20un%20valor%20objetivo%20asociado%2C%20lo%20que%20transforma%20los%20datos%20tabulares%20en%20estructuras%20tridimensionales%0A%20%20%20%20-%20Este%20formato%20es%20indispensable%20para%20alimentar%20modelos%20RNN%2C%20LSTM%20o%20GRU%20en%20Keras%2FTensorFlow.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20FEATURE_COLUMNS%2C%0A%20%20%20%20N_STEPS%2C%0A%20%20%20%20TARGET_COLUMN%2C%0A%20%20%20%20create_sequences%2C%0A%20%20%20%20np%2C%0A%20%20%20%20train_df%2C%0A%20%20%20%20val_df%2C%0A)%3A%0A%20%20%20%20print(%22%5CnProcesando%20secuencias%20para%20Train%20y%20Validation%22)%0A%0A%20%20%20%20X_train_list%2C%20y_train_list%20%3D%20%5B%5D%2C%20%5B%5D%0A%20%20%20%20X_val_list%2C%20y_val_list%20%3D%20%5B%5D%2C%20%5B%5D%0A%0A%20%20%20%20print(%22procesar%20set%20entrenamiento%22)%0A%20%20%20%20unique_products_train%20%3D%20train_df%5B'product_id_encoded'%5D.unique()%0A%20%20%20%20for%20product_id%20in%20unique_products_train%3A%0A%20%20%20%20%20%20%20%20X_prod%2C%20y_prod%20%3D%20create_sequences(train_df%2C%20product_id%2C%20N_STEPS%2C%20FEATURE_COLUMNS%2C%20TARGET_COLUMN)%0A%0A%20%20%20%20%20%20%20%20if%20X_prod%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20X_train_list.append(X_prod)%0A%20%20%20%20%20%20%20%20%20%20%20%20y_train_list.append(y_prod)%0A%0A%20%20%20%20print(%22procesar%20set%20validacion...%22)%0A%20%20%20%20unique_products_val%20%3D%20val_df%5B'product_id_encoded'%5D.unique()%0A%20%20%20%20for%20product_id%20in%20unique_products_val%3A%0A%20%20%20%20%20%20%20%20X_prod%2C%20y_prod%20%3D%20create_sequences(val_df%2C%20product_id%2C%20N_STEPS%2C%20FEATURE_COLUMNS%2C%20TARGET_COLUMN)%0A%0A%20%20%20%20%20%20%20%20if%20X_prod%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20X_val_list.append(X_prod)%0A%20%20%20%20%20%20%20%20%20%20%20%20y_val_list.append(y_prod)%0A%0A%20%20%20%20if%20len(X_train_list)%20%3E%200%3A%0A%20%20%20%20%20%20%20%20X_train%20%3D%20np.concatenate(X_train_list%2C%20axis%3D0)%0A%20%20%20%20%20%20%20%20y_train%20%3D%20np.concatenate(y_train_list%2C%20axis%3D0)%0A%0A%20%20%20%20%20%20%20%20X_val%20%3D%20np.concatenate(X_val_list%2C%20axis%3D0)%0A%20%20%20%20%20%20%20%20y_val%20%3D%20np.concatenate(y_val_list%2C%20axis%3D0)%0A%0A%20%20%20%20%20%20%20%20print(f%22Forma%20de%20X_train%20(Muestras%2C%20Pasos%2C%20Features)%3A%20%7BX_train.shape%7D%22)%0A%20%20%20%20%20%20%20%20print(f%22Forma%20de%20y_train%20(Muestras%2C)%3A%20%7By_train.shape%7D%22)%0A%20%20%20%20%20%20%20%20print(f%22Forma%20de%20X_val%20(Muestras%2C%20Pasos%2C%20Features)%3A%20%7BX_val.shape%7D%22)%0A%20%20%20%20%20%20%20%20print(f%22Forma%20de%20y_val%20(Muestras%2C)%3A%20%7By_val.shape%7D%22)%0A%0A%20%20%20%20%20%20%20%20np.save('X_train.npy'%2C%20X_train)%0A%20%20%20%20%20%20%20%20np.save('y_train.npy'%2C%20y_train)%0A%20%20%20%20%20%20%20%20np.save('X_val.npy'%2C%20X_val)%0A%20%20%20%20%20%20%20%20np.save('y_val.npy'%2C%20y_val)%0A%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20print(%22%5CnNo%20hay%20secuencias.%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20**An%C3%A1lisis%3A**%0A%20%20%20%20-%20Se%20utiliz%C3%B3%20la%20funci%C3%B3n%20create_sequences()%20para%20cada%20producto%20individualmente%2C%20lo%20que%20produjo%20las%20matrices%20X_train%2C%20y_train%2C%20X_val%20y%20y_val.%0A%20%20%20%20-%20La%20conclusi%C3%B3n%20revela%20que%20los%20conjuntos%20poseen%20la%20estructura%20(muestras%2C%207%2C%2030)%2C%20lo%20que%20confirma%2030%20variables%20por%20observaci%C3%B3n%20y%207%20pasos%20temporales.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(df_proc%2C%20pd)%3A%0A%20%20%20%20df_proc_path%20%3D%20'df_processed_features.csv'%0A%20%20%20%20df_proc%5B'created_at'%5D%20%3D%20pd.to_datetime(df_proc%5B'created_at'%5D)%0A%20%20%20%20df_proc.to_csv(df_proc_path%2C%20index%3DFalse)%0A%20%20%20%20print(f%22DataFrame%20procesado%20guardado%20en%20'%7Bdf_proc_path%7D'%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
6237248e3741ffac48033b0e8f9e0e8ab3a1461b4b41c039bdb23b4fb41d216d